#include "StdAfx.h"
#include "cLPSplit.h"

int *getHorSubSplitLine(Point maskPoints[1][4]);


cLPSplit::cLPSplit(void)
{
}

cLPSplit::~cLPSplit(void)
{
}

cLPSplit::cLPSplit(const string &filename) : cImgInterectionDect(filename)	{
	this->maskedImg = this->getMaskedImg();
}

cLPSplit::cLPSplit(const Mat &sourceImg) : cImgInterectionDect( sourceImg ){
	this->maskedImg = this->getMaskedImg();
}

int *cLPSplit::getHorHistogram(const Mat &srcMat){
	int width = srcMat.size().width;
	int height = srcMat.size().height;

	int *horHistogram = (int*) new int[width];
	int count = 0;

	for(int i=0;i<width;i++){
		count = 0;
		for(int j=0;j<height;j++){
			if( srcMat.at<uchar>(j,i) == HISTOGRAM_VALUE ){
				count++;
			}
		}
		horHistogram[i] = count;
	}

	return horHistogram;
}

int *cLPSplit::getVertHistogram(const Mat &srcMat){
	int width = srcMat.size().width;
	int height = srcMat.size().height;

	int *vertHistogram = (int*) new int[height];
	int count = 0;

	for(int i=0;i<height;i++){
		count = 0;
		for(int j=0;j<width;j++){
			if( srcMat.at<uchar>(i,j) == HISTOGRAM_VALUE ){
				count++;
			}
		}
		vertHistogram[i] = count;
	}

	return vertHistogram;
}

int *getHorSubSplitLine(Point maskPoints[1][4]){

	double fa,fb,fc,fd,fe,ff,fg,fh,fi;
	double l1,l2;
	double x0,x1,x2,x3,y0,y1,y2,y3;

	int   *horSplitLine = (int*) new int[9];
	memset(horSplitLine,-1,sizeof(int));

	x0 = maskPoints[0][0].x;
	y0 = maskPoints[0][0].y;
	x1 = maskPoints[0][1].x;
	y1 = maskPoints[0][1].y;
	x2 = maskPoints[0][2].x;
	y2 = maskPoints[0][2].y;
	x3 = maskPoints[0][3].x;
	y3 = maskPoints[0][3].y;

	l1 = sqrt( (y1-y0)*(y1-y0) + (x1-x0)*(x1-x0) );
	l2 = sqrt( (y3-y2)*(y3-y2) + (x3-x2)*(x3-x2) );

	fa =     LINE_A_RELATIVEPOSITION * ( l1 + l2) / 2 + (x0+x3)/2;
	fb = fa+ LINE_B_RELATIVEPOSITION * ( l1 + l2) / 2 ;
	fc = fb+ LINE_C_RELATIVEPOSITOIN * ( l1 + l2) / 2 ;
	fd = fc+ LINE_D_RELATIVEPOSITION * ( l1 + l2) / 2 ;
	fe = fd+ LINE_E_RELATIVEPOSITION * ( l1 + l2) / 2 ;
	ff = fe+ LINE_F_RELATIVEPOSITION * ( l1 + l2) / 2 ;
	fg = ff+ LINE_G_RELATIVEPOSITION * ( l1 + l2) / 2 ;
	fh = fg+ LINE_H_RELATIVEPOSITION * ( l1 + l2) / 2 ;
	fi = fh+ LINE_I_RELATIVEPOSITION * ( l1 + l2) / 2 ;

	horSplitLine[0] = cvRound(fa);
	horSplitLine[1] = cvRound(fb);
	horSplitLine[2] = cvRound(fc);
	horSplitLine[3] = cvRound(fd);
	horSplitLine[4] = cvRound(fe);
	horSplitLine[5] = cvRound(ff);
	horSplitLine[6] = cvRound(fg);
	horSplitLine[7] = cvRound(fh);
	horSplitLine[8] = cvRound(fi);

	return horSplitLine;
}

int *cLPSplit::getHorSplitLine(std::vector<Vec2f> &possibleSplits){
	
	int *horSplitLine = getHorSubSplitLine(this->maskPoints);
	int *lineCount = (int*) new int[9];
	memset(lineCount,1,sizeof(int));

	for(int i=0;i<possibleSplits.size();i++){
		for(int j=0;j<9;j++){
			
			if( (possibleSplits[i][1] <= horSplitLine[j] + HOR_SPLIT_THRESHOLD) && 
				(possibleSplits[i][1] >= horSplitLine[j] - HOR_SPLIT_THRESHOLD) ){
				
					horSplitLine[j] += cvRound(possibleSplits[i][1]);
					lineCount[j]++;

				break;
			}	
		}
	}

	for(int i=0;i<9;i++){
		horSplitLine[i] /= lineCount[i];
	}

	delete[] lineCount;
	return horSplitLine;
}

std::vector<Vec2f> cLPSplit::findPossibleHorSplits(const int *horHistogram,int arrayLength){
	std::vector<Vec2f> possibleSplits;
	if( arrayLength <= 2 )
		return possibleSplits; 
	 
	for(int i=2;i<arrayLength-2;i++){
		if( horHistogram[i] == 0)
			continue;

		int leftVal  = (int)(horHistogram[i-2] * HORHISTOGRAM_THRESHOLD_1 + horHistogram[i-1] * HORHISTOGRAM_THRESHOLD_2) ; 
		int rightVal = (int)(horHistogram[i+2] * HORHISTOGRAM_THRESHOLD_1 + horHistogram[i+1] * HORHISTOGRAM_THRESHOLD_2) ;

		if( horHistogram[i]<= leftVal && horHistogram[i]<=rightVal )
			possibleSplits.push_back(Vec2f((float)horHistogram[i],(float)i));
	}
	return possibleSplits;
}

Mat cLPSplit::doAdaptiveThreshold(const Mat &sourceImg){
	cv::Mat thresholdImg;
	cv::adaptiveThreshold(sourceImg,
		thresholdImg,
		255,
		ADAPTIVE_THRESH_GAUSSIAN_C,
		THRESH_BINARY,
		ADAPTIVETHRESHOLD_BLOCKSIZE,
		ADAPTIVETHRESHOLD_CONSTANT);
	return thresholdImg;
}

vector<Mat> cLPSplit::horSplit(){
	
	Mat binaryImg = this->doAdaptiveThreshold(this->maskedImg);
	vector<Mat> splitedCharacters;


	int *horHistogram = this->getHorHistogram( binaryImg );


	////////////////////////////////////////////////////////
	Mat horHist = Mat(srcImg.size(),CV_8U,Scalar(255));
	for(int i=0;i<srcImg.size().width;i++){
		line(horHist,Point(i,srcImg.size().height),Point(i,srcImg.size().height - horHistogram[i] ),Scalar(0),1,8,0);
	}
	/////////////////////////////////////////////////////////

	vector<Vec2f> possibleSplits = this->findPossibleHorSplits(horHistogram,binaryImg.size().width);
	int *horSplitLines = this->getHorSplitLine(possibleSplits);

	for(int i=0;i<9;i++){
		cv::line(this->srcImgColor,Point(horSplitLines[i],0),Point(horSplitLines[i],this->srcImg.size().height),Scalar(255,0,255),1,8,0);
	}

	namedWindow("asdfasdf",0);
	imshow("asdfasdf",horHist);
	cvWaitKey(0);


	delete[] horSplitLines;
	delete[] horHistogram;
	return splitedCharacters;
}

